package com.duobaoyu.dby.supply.job.service.order.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum;
import com.duobaoyu.dby.channel.adapter.enums.biz.order.OrderStatusEnum;
import com.duobaoyu.dby.common.core.constant.CommonConstants;
import com.duobaoyu.dby.common.core.constant.RequestConstants;
import com.duobaoyu.dby.supply.biz.client.boundary.order.bean.bo.OrderInfoBO;
import com.duobaoyu.dby.supply.biz.client.boundary.order.bean.dto.OrderTaskDTO;
import com.duobaoyu.dby.supply.biz.client.resource.ResourceApiClient;
import com.duobaoyu.dby.supply.biz.client.resource.bean.bo.OrderRuleConfigBO;
import com.duobaoyu.dby.supply.biz.constant.OperateSourceConstants;
import com.duobaoyu.dby.supply.biz.constant.OrderOperateConstants;
import com.duobaoyu.dby.supply.biz.converter.OrderConverter;
import com.duobaoyu.dby.supply.biz.enums.OrderParentTypeEnum;
import com.duobaoyu.dby.supply.biz.producer.SupplyChainMQProducer;
import com.duobaoyu.dby.supply.biz.service.order.OrderService;
import com.duobaoyu.dby.supply.biz.strategy.AbstractSyncOrderStatusStrategy;
import com.duobaoyu.dby.supply.core.framework.util.FrameworkUtils;
import com.duobaoyu.dby.supply.db.entity.order.Order;
import com.duobaoyu.dby.supply.db.repository.order.OrderRepository;
import com.duobaoyu.dby.supply.job.service.order.OrderJobService;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author fengshaoyu
 * @version 1.0.0
 * @date 2023/10/21 17:51
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderJobServiceImpl implements OrderJobService {
    private final OrderService orderService;
    private final OrderRepository orderRepository;
    private final ResourceApiClient resourceApiClient;
    private final SupplyChainMQProducer supplyChainMQProducer;
    private final OrderConverter orderConverter;

    @Override
    public void listSyncOrderStatusData(OrderTaskDTO orderTask){
        List<String> channelCodeList = Arrays.stream(ChannelCodeEnum.values()).map(ChannelCodeEnum::getValue).collect(Collectors.toList());
        if(Objects.nonNull(orderTask) && CollectionUtils.isNotEmpty(orderTask.getChannelCodeList())){
            channelCodeList = orderTask.getChannelCodeList();
        }
        for(String channelCode : channelCodeList){
            List<Integer> statusList = Lists.newArrayList(OrderStatusEnum.RECHARGE.getValue(), OrderStatusEnum.WAIT_SHIP.getValue(), OrderStatusEnum.SHIPPED.getValue());
            Long lastId = null;
            while(true){
                List<Order> orderInfoList = orderRepository.list(Wrappers.lambdaQuery(Order.class)
                        .eq(Order::getChannelCode, channelCode)
                        .eq(Order::getParentType, OrderParentTypeEnum.AFTER_SPLIT.getValue())
                        .in(Order::getOrderStatus, statusList)
                        .gt(Objects.nonNull(lastId), Order::getId, lastId)
                        .orderByAsc(Order::getId)
                        .last("limit " + CommonConstants.HUNDRED));
                if(CollectionUtils.isEmpty(orderInfoList)){
                    break;
                }
                orderInfoList.forEach(o -> {
                    try {
                        MDC.put(RequestConstants.REQUEST_ID, IdUtil.fastSimpleUUID());
                        AbstractSyncOrderStatusStrategy syncOrderStatusStrategy = FrameworkUtils.strategyInstance(AbstractSyncOrderStatusStrategy.class, o.getChannelCode());
                        OrderInfoBO orderInfo = orderConverter.toOrderInfo(o);
                        log.info("同步订单状态处理订单供应链订单号:{},供应链三方交易单号:{},渠道子单号:{}", o.getOrderSn(), o.getOrderTradeSn(), o.getChannelOrderSn());
                        syncOrderStatusStrategy.strategyHandler(orderInfo);
                    } catch (Exception e) {
                        log.warn("订单状态同步异常: orderSn={}", o.getOrderSn(), e);
                    } finally {
                        MDC.remove(RequestConstants.REQUEST_ID);
                    }});
                    Order order = CollUtil.getLast(orderInfoList);
                    lastId = order.getId();
                }
            }
        }

        @Override
        public void autoOrderConfirmComplete() {
            int limit = CommonConstants.HUNDRED;
            for (ChannelCodeEnum item : ChannelCodeEnum.values()) {
                OrderRuleConfigBO orderRuleConfig = resourceApiClient.queryOrderRuleConfig(item.getValue());
                if(ObjectUtils.isEmpty(orderRuleConfig) || ObjectUtils.isEmpty(orderRuleConfig.getOrderRule()) || ObjectUtils.isEmpty(orderRuleConfig.getOrderRule().getShippingOrderConfirmTime())){
                    log.info("message:{},data:{}","当前渠道未配置对应规则", JSON.toJSON(orderRuleConfig));
                    continue;
                }

                Integer[] status = {OrderStatusEnum.SHIPPED.getValue(),OrderStatusEnum.PART_SEND.getValue()};
                while (true) {
                    List<Order> orderList = orderRepository.list(Wrappers.<Order>lambdaQuery()
                            .in(Order::getOrderStatus, Arrays.asList(status))
                            .eq(Order::getParentType, OrderParentTypeEnum.AFTER_SPLIT.getValue())
                            .eq(Order::getChannelCode, item.getValue())
                            .apply("NOW() > adddate(status_change_time, interval " + orderRuleConfig.getOrderRule().getShippingOrderConfirmTime() + " day)")
                            .last("limit " + limit));
                    if (CollectionUtils.isEmpty(orderList)) {
                        break;
                    }

                    Map<Integer, List<Order>> orderStatusMap = orderList.stream().collect(Collectors.groupingBy(Order::getOrderStatus));
                    orderStatusMap.forEach((k,v) -> {
                        List<String> orderSnList = v.stream().map(Order::getOrderSn).collect(Collectors.toList());
                        orderService.updateStatusByOrderSnList(orderSnList,OrderStatusEnum.COMPLETE,OrderStatusEnum.getOrderSubStatusEnum(k), OperateSourceConstants.JOB, OrderOperateConstants.BACKSTAGE_COMPLETE,null);
                    });

                    orderList.stream()
                            .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Order::getSupplyTradeSn))), ArrayList::new))
                            .forEach(order -> supplyChainMQProducer.orderAlterSend(order.getSupplyTradeSn(),order.getServerName()));
                }
            }
        }
}
